%{

#include <iostream>

void yyerror( char* errorString );
extern int yylineno;

void printMatch( const std::string& tokenType )
{
  std::cout << "Match: \"" << yytext << "\"\t of type \"" << tokenType << "\"" << std::endl;
}

%}

whitespace    [ \t]+
delimiter     [\[\]\(\);:,]
digit         [0-9]
letter        [a-zA-Z]
sign          "+"|"-"
assignop      ":="
addop         "+"|"-"|"or"
mulop         [\*\/]|"and"
relop         "="|"<"|"<="|">"|">="|"!="
integer       {digit}+
real          {integer}\.{integer}{scale}?
scale         "E"{sign}{integer}
identifier    {letter}({letter}|{digit})*
character     "’"."’"
boolean       "true"|"false"

%x IN_COMMENT

%%

\n                          { yylineno++; }

"program"                   printMatch("program");

"begin"                     printMatch("begin");
"end"                       printMatch("end");

"type"                      printMatch("type");
"integer"                   printMatch("integer");
"boolean"                   printMatch("boolean");
"char"                      printMatch("char");
"array"                     printMatch("array");

"procedure"                 printMatch("procedure");

"if"                        printMatch("if");
"then"                      printMatch("then");
"else"                      printMatch("else");
"endif"                     printMatch("endif");

"while"                     printMatch("while");
"endwhile"                  printMatch("endwhile");
"do"                        printMatch("do");
"read"                      printMatch("read");
"write"                     printMatch("write");

"return"                    printMatch("return");

"not"                       printMatch("not");

{whitespace}                ;

{delimiter}                 printMatch("delimiter");

{assignop}                  printMatch("assignop");

{addop}                     printMatch("addop");
{mulop}                     printMatch("mulop");
{relop}                     printMatch("relop");

{integer}                   printMatch("integer");
{real}                      printMatch("real");
{character}                 printMatch("character");
{boolean}                   printMatch("boolean");

{identifier}                printMatch("identifier");

.                           yyerror( "Invalid character." );

"/*"                        BEGIN(IN_COMMENT);

<IN_COMMENT>
{
     "*/"      BEGIN(INITIAL);
     [^*\n]+   ; // ignore everything inside the comments
     "*"       ; // ignore the lone star
     \n        yylineno++;
}


%%

int yywrap()
{
  return 1;
}

void yyerror( char* str )
{
  printf( "Syntax error at line: %d - %s\n", yylineno, str ); exit( 0 );
}

int main( void )
{
  yylex();
  return 0;
}
